package com.loong.collect.snmp4j;

import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.event.ResponseListener;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.DefaultPDUFactory;
import org.snmp4j.util.TableEvent;
import org.snmp4j.util.TableUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

/**
 * Created by 梁浩峰 on 2016/8/23 16:11.
 */
public class SNMPtest {

    public static void syncGetBulk(String hosts, String port, String readName,String oid) {
        try {
            Snmp snmp = new Snmp(new DefaultUdpTransportMapping()); //构造一个UDP
            snmp.listen(); //开始监听snmp消息

            CommunityTarget target = new CommunityTarget();
            target.setCommunity(new OctetString(readName));//snmpv2的团体名
            target.setVersion(SnmpConstants.version2c);  //snmp版本
            target.setAddress(new UdpAddress(hosts+"/"+port));
            target.setTimeout(60000); //时延
            target.setRetries(1); //重传

            PDU pdu = new PDU();  //a SNMP protocol data unit
            //使用GETBULK方式获取数据,无论什么方式取oid,都是取叶子节点，叶子节点的父节点都不会取到
            pdu.setType(PDU.GETBULK);

            //snmp getBulk独有
            pdu.setMaxRepetitions(10); //每个OID通过GETBULK方式获取多少个数据
            /*偏移量，假设有两个oid,0代表两个oid都取3000个叶子oid,1代表第一个取它最近的第一个oid,第二个取3000个oid,
             * 大于1的数代表两个oid都是取他们最近的第一个oid
             */
            pdu.setNonRepeaters(0);

            //添加oid,可以多个
            pdu.add(new VariableBinding(new OID(oid)));
            ResponseEvent responseEvent = snmp.send(pdu, target);
            PDU response = responseEvent.getResponse();

            if (response == null) {
                System.out.println("TimeOut...");
            } else {
                if (response.getErrorStatus() == PDU.noError) {
                    //读取数据
                    Vector<? extends VariableBinding> vbs = response
                            .getVariableBindings();
//                    List<SnmpResult> result = new ArrayList<SnmpResult>(vbs.size());
                    for (VariableBinding vb : vbs) {
//                        result.add(new SnmpResult(vb.getOid().toString(),vb.getVariable().toString()));
                        System.out.println(vb.getOid().toString()+"==>"+vb.getVariable().toString());
                    }
                } else {
                    System.out
                            .println("Error:" + response.getErrorStatusText());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static void walk(String hosts, String port, String readName,String oid) {
        try {
            Snmp snmp = new Snmp(new DefaultUdpTransportMapping()); // 构造一个UDP
            snmp.listen(); // 开始监听snmp消息

            CommunityTarget target = new CommunityTarget();
            target.setCommunity(new OctetString(readName));// snmpv2的团体名
            target.setVersion(SnmpConstants.version2c); // snmp版本
            target.setAddress(new UdpAddress(hosts+"/"+port));
            target.setTimeout(60000); // 时延
            target.setRetries(1); // 重传

            TableUtils utils = new TableUtils(snmp, new DefaultPDUFactory(
                    PDU.GETNEXT));// GETNEXT or GETBULK
            utils.setMaxNumRowsPerPDU(5); // only for GETBULK, set max-repetitions, default is 10
            OID[] columnOids = new OID[] {new OID(oid)};
            // If not null, all returned rows have an index in a range (lowerBoundIndex, upperBoundIndex]
            //lowerBoundIndex,upperBoundIndex都为null时返回所有的叶子节点。 必须具体到某个OID,,否则返回的结果不会在(lowerBoundIndex, upperBoundIndex)之间
            List<TableEvent> l = utils.getTable(target, columnOids,null
                    ,null);
            for (TableEvent e : l) {
                VariableBinding[] bindings = e.getColumns();
                String s = bindings[0].toValueString();
                if(s!=null&&!s.equals("")){
                    System.out.println( bindings[0].getOid()+"==>"+s);
                }
            }


        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    public static void asyncGetNext(String hosts, String port, String readName,String oid) {
        try {
            Snmp snmp = new Snmp(new DefaultUdpTransportMapping()); // 构造一个UDP
            snmp.listen(); // 开始监听snmp消息

            CommunityTarget target = new CommunityTarget();
            target.setCommunity(new OctetString(readName));// snmpv2的团体名
            target.setVersion(SnmpConstants.version2c); // snmp版本
            target.setAddress(new UdpAddress(hosts+"/"+port));
            target.setTimeout(60000); // 时延
            target.setRetries(1); // 重传

            PDU pdu = new PDU(); // a SNMP protocol data unit
            pdu.setType(PDU.GETNEXT);

            // 添加oid,可以多个
            pdu.add(new VariableBinding(new OID(oid)));

            // 设置监听对象
            ResponseListener listener = new ResponseListener() {
                public void onResponse(ResponseEvent event) {
                    try {
                        PDU response = event.getResponse();

                        if (response == null) {
                            System.out.println("TimeOut...");
                        } else {
                            if (response.getErrorStatus() == PDU.noError) {
                                // 读取数据
                                Vector<? extends VariableBinding> vbs = response
                                        .getVariableBindings();
                                List<SnmpResult> result = new ArrayList<SnmpResult>(
                                        vbs.size());
                                for (VariableBinding vb : vbs) {
                                    result.add(new SnmpResult(vb.getOid().toString(), vb
                                            .getVariable().toString()));
                                }
                                System.out.println(result.toString());
                            } else {
                                System.out
                                        .println("Error:" + response.getErrorStatusText());
                            }
                        }
                    }catch(Exception e) {
                        e.printStackTrace();
                    }
                }
            };
            snmp.send(pdu, target,null, listener);  //设置异步处理
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    public static void main(String[] args){
        String oid="1.3.6.1.2.1.25.2.3.1.4";

        if(args.length<3){
            System.out.println("至少三个参数");
            System.exit(-1);
        }else{
            asyncGetNext(args[0],args[1],args[2],oid);
        }
//        syncGetBulk();
//        walk();
//        asyncGetNext();
    }


}
